/** @brief Define commonly used classes or functions.
 *
 *  util.h
 *  kangmodb
 *
 *  Created by 강모 김 on 11. 4. 23..
 *  Copyright 2011 강모소프트. All rights reserved.
 *
 */

#ifndef _KD_UTIL_H_
#define _KD_UTIL_H_ (1)

#include "types.h"

/* Macro to find the minimum of two numeric values.
 */
#define MIN(x,y) ((x)<(y)?(x):(y))

#define MAX(x,y) ((x)>(y)?(x):(y))

namespace util {
	int string_compare(const char * string1, const int string1_len, const char * string2, const int string2_len );
};

/** @brief See if a given size is power of two, such as 2, 4, 8, 16, 32, 64, 128, ... 
 */
inline bool kdMemIsPowerOfTwo( uptr size )
{
	for(;(size & 0x1) == 0; size = size >> 1);
	
	// chunkSize should be power of 2. It means there should be only one bit whose value is 1.
	return size == 0x1;
}


/** @brief Get the number of bits aligned in a pointer.
 * Get the number of consecutive 0 bits on the lowest bits 
 */
inline u32 kdMemGetAlignedBits( uptr ptr )
{
	u32 alignedBits = 0;
	for(;(ptr & 0x1) == 0; ptr = ptr >> 1)
	    alignedBits ++;
	
	return alignedBits;
}

/** @brief See if a pointer is aligned to 8 byte bounday.
 */
inline bool kdMemIsAlignedBy8Byte( uptr ptr )
{
	// Check if the lowest three bits are zero.
	return ((ptr >> 3) << 3) == ptr;
}

/** @brief Align the memory address by alignSize, which is power of two.
 */
inline uptr kdMemAlign( uptr ptr, u32 alignSize)
{
	KD_ASSERT( kdMemIsPowerOfTwo(alignSize) );
	u32 alignBits = kdMemGetAlignedBits(alignSize);
	
	// Align the pointer by alignBits.
	return (ptr >> alignBits) << alignBits;
}

/** @brief Align the memory address by alignSize, which is power of two; void* version.
 */
inline void* kdMemAlign( void * ptr, u32 alignSize)
{
	return (void*)kdMemAlign((uptr)ptr, alignSize);
}

/** @brief Align the memory address by alignSize, which is power of two. Align the address to the direction that it increases.
 */
inline uptr kdMemAlignUp( uptr ptr, u32 alignSize)
{
	uptr aligned = kdMemAlign( ptr, alignSize);
	if ( aligned != ptr ) // Aligned down.
	{
		// Align up
		aligned = aligned + alignSize;
	}
	return aligned;
}

/** @brief Align the memory address by alignSize, which is power of two. Align the address to the direction that it increases. void * version.
 */
inline void* kdMemAlignUp( void * ptr, u32 alignSize)
{
	return (void*)kdMemAlignUp((uptr)ptr, alignSize);
}


#endif /* _KD_UTIL_H_ */